/*###################################################################*
#
# MP (Mitchell Pell) Base - CrossPlatform Base Utilities.
# Copyright (C) 2014  Mitchell Pell
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
####################################################################*/
#ifndef GL_TCP_CLIENT_H
#define GL_TCP_CLIENT_H

#include "TcpSession.h"
using namespace boost::asio::ip;
using mp_base::interfaces::RecursiveLockingMutex;
using mp_base::utility::Pause;
using mpgl_engine::driver::gl_console::GlConsole;

namespace mpgl_engine{ namespace application{ namespace net {

	/*!----------------------------------------------------------------
	*	@enum		TcpSessionMode
	*	@brief
	*
	*	@author		Mitchell Pell
	*	@date		01/06/2014
	-----------------------------------------------------------------*/
	enum class TcpClientConnectionMode
	{
		/*!  */
		DISCONNECTED = 0x00,
		/*!  */
		CONNECTING = 0x01,
		/*!  */
		CONNECTED = 0x02,
		/*!  */
		UNKNOWN = 0xFF
	};

	/*!----------------------------------------------------------------
	*	@class		TcpClient
	*	@brief		This class represents a TCP Client, inheriting from
	*				the TCP Session base class. The Client variant is
	*				allowed a single connection and has the ability
	*				to search for, resolve, and connect to servers.
	*
	*	@author		Mitchell Pell
	*	@date		01/06/2014
	*	@version	1.1
	*
	*	@revisions	Revision History:
	*
	*					- Version 1.1 01/06/2014
	*						-# Added the enum TcpClientConnectionMode
	*						to replace all the volatile boolean 
	*						flags used.
	*
	*						-# Fixed the following:
	*							+ TcpClient dose not crash while trying
	*							to disconnect while connecting.
	*
	*							+ TcpClient does not crash while trying
	*							to reconnect after failure to connect.
	*
	*					- Version 1.0 01/04/2014
	*						-# Initial Make
	*
	-----------------------------------------------------------------*/
	class TcpClient : public TcpSession
	{
	public:
		/*! Default constructor. */
		TcpClient(	GlConsole* console = NULL,
					io_service* ioService = NULL);
		/*! Destructor. */
		virtual ~TcpClient();

		/*! Initializes the TcpClient. */
		virtual void Initialize(){SetResolver(); m_initialized = true;}
		/*! Updates the TcpClient and any TcpConnections. */
		virtual void Update();

		/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		>>  Connect Operation
		/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

		/*! 
		* @brief	Called to connect to a server. 
		* 
		* @note		Currently connects to localhost only, will enable 
		*			searching and parsing.
		*/
		virtual void Connect();

		/*! Handles the result of the resolver attempting to connect to a server. */
		void HandleResolve(
			TcpClient* client, const boost::system::error_code& error,
			tcp::resolver::iterator endpoint_iterator);

		/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		>>  Disconnect Operations
		/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

		/*! Disconnects and destroys the current connection(s) emidietly. */
		virtual void Disconnect();

		/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		>>  Accessors / Mutators
		/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

		/*! Sets the resolver using the given IO Service. */
		void SetResolver(){ if (m_ioService != NULL){
			m_resolver = new tcp::resolver(*m_ioService); }}
		/*! Clears the current resolver. */
		void ClearResolver(){ if (m_resolver != NULL){
				delete m_resolver; m_resolver = NULL;}}
		const TcpClientConnectionMode GetConnectionMode() const 
			{ return m_connectionMode; }
		const bool DisconnectRequested() const 
			{ return m_stopRequest; }


		/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		>>  Members
		/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
	protected:
		/*! Resolver for finding and connecting to a server. */
		tcp::resolver*			m_resolver;

		/*! Connected to server flag. */
		volatile TcpClientConnectionMode m_connectionMode;
	};
}}}

#endif